// Type.cpp : implementation file
#include "stdafx.h"
#include "Token.h"

bool Token::operator==(Token::const_reference To) const{
	return 	(this->m_ID == To.m_ID);
}

Token::Token(const string& ss):SyntacticSugar(ss){}
Token::Token(Token::const_reference To):
AppObject(To),SyntacticSugar(To.SyntacticSugar){}
Token::~Token(){}



bool Token::hasSyntax( ) const {return (this->SyntacticSugar.size( ) > 0);}
void Token::setSyntax(string NewSyntax){this->SyntacticSugar = NewSyntax;}
const string& Token::getSyntax() const {return this->SyntacticSugar;}

string Token::toString() const{return ((hasSyntax( ))?SyntacticSugar:view());}
string Token::view() const{return string("_") + AppObject::toString( );}
Token::pointer Token::replaceAll(Token::const_reference To1, Token::const_reference To2) const{
	if(this->operator ==(To1)) return To2.clone();
	return this->clone();
	}


TokenPair* TokenPair::replaceAll(Token::const_reference To1, Token::const_reference To2) const{
	Token::pointer NewFirst = this->first->replaceAll(To1, To2);
	Token::pointer NewSecond = this->second->replaceAll(To1, To2);
	TokenPair* TPPtr = new TokenPair(*NewFirst, *NewSecond);
	delete NewFirst;
	delete NewSecond;
	return TPPtr;
}
 
TokenPair* TokenPair::clone() const{
	  return new TokenPair(*this);
}		
void TokenPair::destroy(){
		if(this->first){
			delete this->first;
			this->first=NULL;
			}
		if(this->second){
			delete this->second;
			this->second = NULL;
			}
}
void TokenPair::copy(TokenPair::const_reference TP){
	  destroy();
	  if(TP.first) this->first = TP.first->clone();
	  if(TP.second) this->second = TP.second->clone();
	}

TokenPair::TokenPair(TokenPair::const_reference TP){
	this->first = NULL;
	this->second = NULL;
	copy(TP);
	}
TokenPair::TokenPair(Token::const_reference TO1, Token::const_reference TO2){
	this->first = TO1.clone();
	this->second = TO2.clone();
	}
TokenPair::~TokenPair(){
	destroy();
	}
bool TokenPair::operator ==(TokenPair::const_reference TP) const{
	return 
			((this->first->operator ==(*TP.first))
			&&(this->second->operator ==(*TP.second)));
	}
TokenPair::const_reference TokenPair::operator =(TokenPair::const_reference TP){
		if(&TP != this) copy(TP);
		return *this;
	}
string TokenPair::toString() const{return string("(")+first->toString()+")("+second->toString()+")";}
Token::pointer TokenPair::replaceAllOccurencesOfFirstInSecondBy(Token::const_reference To) const{
	try{
       		return this->second->replaceAll(*(this->first), To);
	}
  	catch(AppObject err){
		throw err;
	}
}
Token::pointer TokenPair::replaceAllOccurencesOfArgumentBySecondInFirst(Token::const_reference To) const{
       Token::pointer Res = this->first->replaceAll(To, *(this->second));
       return Res;
}



TokenVector::TokenVector(Token::const_reference To){
	push_back(To);
	}

TokenVector::TokenVector(vector<Token *> TV){
	for(size_t i=0; i<TV.size( ); i++)
		push_back(*TV[i]);
}
TokenVector::TokenVector(const TokenVector& TV){
	for(size_t i=0; i<TV.size( ); i++)
		push_back(TV[i]);
}

TokenVector::~TokenVector( ){
	for(size_t i=0; i<size( ); i++)
		delete (&(operator[ ](i)));
}

TokenVector* TokenVector::replaceAll(Token::const_reference To1, Token::const_reference To2) const{
	vector<Token::pointer> TV;
	for(size_t i=0; i<size( ); i++)
		TV.push_back(operator[ ](i).replaceAll(To1, To2));

	TokenVector* Res = new TokenVector(TV);
	for(size_t j=0; j<TV.size( ); j++)
		delete &(TV[j]);

	return Res; 	
}

TokenVector* TokenVector::clone( ) const{
	return new TokenVector(*this);
}


string TokenVector::toString() const{
	string Res("[");
	for(size_t i=0; i<size( ); i++){
		Res += (operator[ ](i)).toString();
		if(i < size( )-1) Res += string(", ");
	}
	Res += string("]");
	return Res;
}

size_t TokenVector::complexity() const{
	size_t Sum = 0;
	for(size_t i=0; i<size( ); i++)
		Sum += (operator[ ](i)).complexity( );
	return Sum;
}


void TokenVector::push_back(Token::const_reference To){
	vector<Token::pointer>::push_back(To.clone( ));
}

Token::const_reference TokenVector::operator[ ] (size_t index) const{
	if(index >= size( )) throw Token::exception("Token::const_reference operator[ ] (size_t index) const");
	return *(vector<Token::pointer>::operator [](index));
	}











